package cn.i5.remoteinvocationcontrol.core;

import cn.i5.remoteinvocationcontrol.annotation.RemoteInvocationControl;
import cn.i5.remoteinvocationcontrol.config.RemoteInvocationControlConfig;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Method;

/**
 * 远程调用控制拦截器
 *
 * @author mc0710
 */
@Aspect
@Component
@Order(1)
@Slf4j
public class RemoteInvocationControlInterceptor {

    @Resource
    RemoteInvocationControlConfig remoteInvocationControlConfig;

    /**
     * 校验,方法上
     */
    @Around(value = "@annotation(cn.i5.remoteinvocationcontrol.annotation.RemoteInvocationControl)")
    public Object handleMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method targetMethod = methodSignature.getMethod();
        Method realMethod = joinPoint.getTarget().getClass().getDeclaredMethod(methodSignature.getName(),
                targetMethod.getParameterTypes());
        RemoteInvocationControlFacade remoteInvocationControlFacade = new RemoteInvocationControlFacade();
        RemoteInvocationControl remoteInvocationControl = realMethod.getAnnotation(RemoteInvocationControl.class);
        remoteInvocationControlFacade.check(remoteInvocationControl, remoteInvocationControlConfig);
        return joinPoint.proceed();
    }

    /**
     * 校验,类上
     */
    @Around(value = "@within(cn.i5.remoteinvocationcontrol.annotation.RemoteInvocationControl)")
    public Object handleClass(ProceedingJoinPoint joinPoint) throws Throwable {
        // 获取到类
        Class target = joinPoint.getTarget().getClass();
        RemoteInvocationControl remoteInvocationControl = (RemoteInvocationControl) target.getAnnotation(RemoteInvocationControl.class);
        RemoteInvocationControlFacade remoteInvocationControlFacade = new RemoteInvocationControlFacade();
        remoteInvocationControlFacade.check(remoteInvocationControl, remoteInvocationControlConfig);
        return joinPoint.proceed();
    }

}
